gsk_render_node_unref
GskRenderNodeType
gsk_render_node_get_node_type
+gsk_render_node_draw
gsk_render_node_set_opacity
GskBlendMode
gsk_render_node_set_blend_mode
}
-static void
-gsk_cairo_renderer_render_node (GskCairoRenderer *self,
- GskRenderNode *node,
- cairo_t *cr)
-{
- gboolean pop_group = FALSE;
- graphene_rect_t frame;
-
- cairo_save (cr);
-
- gsk_render_node_get_bounds (node, &frame);
- GSK_NOTE (CAIRO, g_print ("CLIP = { .x = %g, .y = %g, .width = %g, .height = %g }\n",
- frame.origin.x, frame.origin.y,
- frame.size.width, frame.size.height));
-
- if (!GSK_RENDER_MODE_CHECK (GEOMETRY))
- {
- cairo_rectangle (cr, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
- cairo_clip (cr);
- }
-
- if (gsk_render_node_get_opacity (node) != 1.0)
- {
- GSK_NOTE (CAIRO, g_print ("Pushing opacity group (opacity:%g)\n",
- gsk_render_node_get_opacity (node)));
- cairo_push_group (cr);
- pop_group = TRUE;
- }
-
- GSK_NOTE (CAIRO, g_print ("Rendering node %s[%p] at %g, %g\n",
- node->name,
- node,
- frame.origin.x, frame.origin.y));
-
- switch (gsk_render_node_get_node_type (node))
- {
- case GSK_NOT_A_RENDER_NODE:
- default:
- g_assert_not_reached ();
- break;
-
- case GSK_CONTAINER_NODE:
- {
- guint i;
- GSK_NOTE (CAIRO, g_print ("Drawing %d children of node [%p]\n",
- gsk_container_node_get_n_children (node),
- node));
- for (i = 0; i < gsk_container_node_get_n_children (node); i++)
- {
- gsk_cairo_renderer_render_node (self, gsk_container_node_get_child (node, i), cr);
- }
- }
- break;
-
- case GSK_TEXTURE_NODE:
- {
- GskTexture *texture = gsk_texture_node_get_texture (node);
- cairo_surface_t *surface = gsk_texture_download (texture);
-
- cairo_set_source_surface (cr, surface, frame.origin.x, frame.origin.y);
- cairo_paint (cr);
- cairo_surface_destroy (surface);
- }
- break;
-
- case GSK_CAIRO_NODE:
- {
- cairo_set_source_surface (cr, gsk_cairo_node_get_surface (node), frame.origin.x, frame.origin.y);
- cairo_paint (cr);
- }
- break;
-
- case GSK_TRANSFORM_NODE:
- {
- graphene_matrix_t mat;
- cairo_matrix_t ctm;
-
- gsk_transform_node_get_transform (node, &mat);
- if (graphene_matrix_to_2d (&mat, &ctm.xx, &ctm.yx, &ctm.xy, &ctm.yy, &ctm.x0, &ctm.y0))
- {
- GSK_NOTE (CAIRO, g_print ("CTM = { .xx = %g, .yx = %g, .xy = %g, .yy = %g, .x0 = %g, .y0 = %g }\n",
- ctm.xx, ctm.yx,
- ctm.xy, ctm.yy,
- ctm.x0, ctm.y0));
- cairo_transform (cr, &ctm);
- }
- else
- g_critical ("Invalid non-affine transformation for node %p", node);
-
- gsk_cairo_renderer_render_node (self, gsk_transform_node_get_child (node), cr);
- }
- break;
- }
-
- if (GSK_RENDER_MODE_CHECK (GEOMETRY))
- {
- cairo_save (cr);
- cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
- cairo_rectangle (cr, frame.origin.x - 1, frame.origin.y - 1, frame.size.width + 2, frame.size.height + 2);
- cairo_set_line_width (cr, 2);
- cairo_set_source_rgba (cr, 0, 0, 0, 0.5);
- cairo_stroke (cr);
- cairo_restore (cr);
- }
-
- if (pop_group)
- {
- cairo_pop_group_to_source (cr);
- cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
- cairo_paint_with_alpha (cr, gsk_render_node_get_opacity (node));
- }
-
- cairo_restore (cr);
-}
-
static void
gsk_cairo_renderer_render (GskRenderer *renderer,
GskRenderNode *root)
gsk_profiler_timer_begin (profiler, self->profile_timers.cpu_time);
#endif
- gsk_cairo_renderer_render_node (self, root, cr);
+ gsk_render_node_draw (root, cr);
#ifdef G_ENABLE_DEBUG
cpu_time = gsk_profiler_timer_end (profiler, self->profile_timers.cpu_time);
node->is_mutable = FALSE;
}
+/**
+ * gsk_render_node_draw:
+ * @node: a #GskRenderNode
+ * @cr: cairo context to draw to
+ *
+ * Draw the contents of @node to the given cairo context.
+ *
+ * Typically, you'll use this function to implement fallback rendering
+ * of #GskRenderNodes on an intermediate Cairo context, instead of using
+ * the drawing context associated to a #GdkWindow's rendering buffer.
+ *
+ * For advanced nodes that cannot be supported using Cairo, in particular
+ * for nodes doing 3D operations, this function may fail.
+ **/
+void
+gsk_render_node_draw (GskRenderNode *node,
+ cairo_t *cr)
+{
+ g_return_if_fail (GSK_IS_RENDER_NODE (node));
+ g_return_if_fail (cr != NULL);
+
+ cairo_save (cr);
+
+ if (!GSK_RENDER_MODE_CHECK (GEOMETRY))
+ {
+ graphene_rect_t frame;
+
+ gsk_render_node_get_bounds (node, &frame);
+ GSK_NOTE (CAIRO, g_print ("CLIP = { .x = %g, .y = %g, .width = %g, .height = %g }\n",
+ frame.origin.x, frame.origin.y,
+ frame.size.width, frame.size.height));
+
+ cairo_rectangle (cr, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
+ cairo_clip (cr);
+ }
+
+ GSK_NOTE (CAIRO, g_print ("Rendering node %s[%p]\n",
+ node->name,
+ node));
+
+ node->node_class->draw (node, cr);
+
+ if (GSK_RENDER_MODE_CHECK (GEOMETRY))
+ {
+ graphene_rect_t frame;
+
+ gsk_render_node_get_bounds (node, &frame);
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+ cairo_rectangle (cr, frame.origin.x - 1, frame.origin.y - 1, frame.size.width + 2, frame.size.height + 2);
+ cairo_set_line_width (cr, 2);
+ cairo_set_source_rgba (cr, 0, 0, 0, 0.5);
+ cairo_stroke (cr);
+ }
+
+ cairo_restore (cr);
+}
+
+
GDK_AVAILABLE_IN_3_90
const char * gsk_render_node_get_name (GskRenderNode *node);
+GDK_AVAILABLE_IN_3_90
+void gsk_render_node_draw (GskRenderNode *node,
+ cairo_t *cr);
G_END_DECLS
#endif /* __GSK_RENDER_NODE_H__ */
#include "gskdebugprivate.h"
#include "gskrendererprivate.h"
-#include "gsktexture.h"
+#include "gsktextureprivate.h"
/*** GSK_TEXTURE_NODE ***/
{
}
+static void
+gsk_texture_node_draw (GskRenderNode *node,
+ cairo_t *cr)
+{
+ GskTextureNode *self = (GskTextureNode *) node;
+ cairo_surface_t *surface;
+
+ surface = gsk_texture_download (self->texture);
+
+ cairo_save (cr);
+
+ cairo_translate (cr, self->bounds.origin.x, self->bounds.origin.y);
+ cairo_scale (cr,
+ self->bounds.size.width / gsk_texture_get_width (self->texture),
+ self->bounds.size.height / gsk_texture_get_height (self->texture));
+
+ cairo_set_source_surface (cr, surface, 0, 0);
+ cairo_paint (cr);
+
+ cairo_restore (cr);
+
+ cairo_surface_destroy (surface);
+}
+
static void
gsk_texture_node_get_bounds (GskRenderNode *node,
graphene_rect_t *bounds)
"GskTextureNode",
gsk_texture_node_finalize,
gsk_texture_node_make_immutable,
+ gsk_texture_node_draw,
gsk_texture_node_get_bounds
};
{
}
+static void
+gsk_cairo_node_draw (GskRenderNode *node,
+ cairo_t *cr)
+{
+ GskCairoNode *self = (GskCairoNode *) node;
+
+ if (self->surface == NULL)
+ return;
+
+ cairo_set_source_surface (cr, self->surface, self->bounds.origin.x, self->bounds.origin.y);
+ cairo_paint (cr);
+}
+
static void
gsk_cairo_node_get_bounds (GskRenderNode *node,
graphene_rect_t *bounds)
"GskCairoNode",
gsk_cairo_node_finalize,
gsk_cairo_node_make_immutable,
+ gsk_cairo_node_draw,
gsk_cairo_node_get_bounds
};
}
}
+static void
+gsk_container_node_draw (GskRenderNode *node,
+ cairo_t *cr)
+{
+ GskContainerNode *container = (GskContainerNode *) node;
+ guint i;
+
+ for (i = 0; i < container->n_children; i++)
+ {
+ gsk_render_node_draw (container->children[i], cr);
+ }
+}
+
static void
gsk_container_node_get_bounds (GskRenderNode *node,
graphene_rect_t *bounds)
"GskContainerNode",
gsk_container_node_finalize,
gsk_container_node_make_immutable,
+ gsk_container_node_draw,
gsk_container_node_get_bounds
};
gsk_render_node_make_immutable (self->child);
}
+static void
+gsk_transform_node_draw (GskRenderNode *node,
+ cairo_t *cr)
+{
+ GskTransformNode *self = (GskTransformNode *) node;
+ cairo_matrix_t ctm;
+
+ if (graphene_matrix_to_2d (&self->transform, &ctm.xx, &ctm.yx, &ctm.xy, &ctm.yy, &ctm.x0, &ctm.y0))
+ {
+ GSK_NOTE (CAIRO, g_print ("CTM = { .xx = %g, .yx = %g, .xy = %g, .yy = %g, .x0 = %g, .y0 = %g }\n",
+ ctm.xx, ctm.yx,
+ ctm.xy, ctm.yy,
+ ctm.x0, ctm.y0));
+ cairo_transform (cr, &ctm);
+
+ gsk_render_node_draw (self->child, cr);
+ }
+ else
+ {
+ graphene_rect_t bounds;
+
+ gsk_render_node_get_bounds (node, &bounds);
+
+ cairo_set_source_rgb (cr, 255 / 255., 105 / 255., 180 / 255.);
+ cairo_rectangle (cr, bounds.origin.x, bounds.origin.x, bounds.size.width, bounds.size.height);
+ cairo_fill (cr);
+ }
+}
+
static void
gsk_transform_node_get_bounds (GskRenderNode *node,
- graphene_rect_t *bounds)
+ graphene_rect_t *bounds)
{
GskTransformNode *self = (GskTransformNode *) node;
graphene_rect_t child_bounds;
"GskTransformNode",
gsk_transform_node_finalize,
gsk_transform_node_make_immutable,
+ gsk_transform_node_draw,
gsk_transform_node_get_bounds
};
const char *type_name;
void (* finalize) (GskRenderNode *node);
void (* make_immutable) (GskRenderNode *node);
+ void (* draw) (GskRenderNode *node,
+ cairo_t *cr);
void (* get_bounds) (GskRenderNode *node,
graphene_rect_t *bounds);
};